//
//  ZHContentView.swift
//  ZHPageView
//
//  Created by Rango on 2020/8/27.
//  Copyright © 2020 Rango. All rights reserved.
//

import UIKit

class ZHContentView: UIView {
    // MARK: - ---> Public
    var didScrollViewDidEndScrollingAnimation: ((UIScrollView, Bool, Int, Bool) -> Void)?
    var didScrollViewDidScroll: ((UIScrollView, Bool, ZHScrollDirection) -> Void)?
    var didScrollViewWillBeginDragging: ((UIScrollView) -> Void)?
    
    // MARK: - ---> Private
    private weak var parent: UIViewController? // weak 才能被正常释放
    private var childVces: [UIViewController] = []
    private var style: ZHSegmentStyle = ZHSegmentStyle()
    private var cWidth: CGFloat { contentView.frame.width }
    private var isFirstAdd: Bool = true
    private var isScroll: Bool = true
    private var beginOffset: CGFloat = 0
    private var lastIndex: Int = 0
    //private var nextIndex: Int = 0
    // MARK: - ---> Life Cycle
    /// 初始化
    /// - Parameters:
    ///   - frame: frame description
    ///   - style: style description
    ///   - childVces: childVces description
    ///   - parent: parent description
    init(frame: CGRect,
         style: ZHSegmentStyle,
         childVces: [UIViewController],
         parent: UIViewController) {
        super.init(frame: frame)
        
        self.parent = parent
        self.childVces = childVces
        self.style = style
        self.lastIndex = style.defaultIndex
        
        initSubviews()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        initSubviews()
        fatalError("init(coder:) has not been implemented")
    }
    deinit {
        print("\(#file)-\(#line)-\(#function)--->销毁")
    }
    /// 布局子视图
    override func layoutSubviews() {
        super.layoutSubviews()
        // TODO: 布局子视图
        let kWidth = bounds.width
        let kHeight = bounds.height
        
        let contentViewX: CGFloat = 0
        let contentViewY: CGFloat = 0
        let contentViewW: CGFloat = kWidth
        let contentViewH: CGFloat = kHeight - contentViewY
        contentView.frame = CGRect(x: contentViewX, y: contentViewY, width: contentViewW, height: contentViewH)
        contentView.contentSize = CGSize(width: CGFloat(childVces.count) * kWidth, height: 0)
        
        contentLayoutSubviews()
        
        isFirstAdd = false
    }
    // 只布局当前要展示的,适配横竖屏切换
    private func contentLayoutSubviews() {
        var aX: CGFloat = 0
        let aY: CGFloat = 0
        let aW: CGFloat = cWidth
        let aH: CGFloat = contentView.frame.height
        for item in childVces.enumerated() {
            if isFirstAdd {
                if item.offset == style.defaultIndex {
                    aX = CGFloat(style.defaultIndex) * aW
                    item.element.view.frame = CGRect(x: aX, y: aY, width: aW, height: aH)
                    contentView.addSubview(item.element.view)
                    contentView.setContentOffset(CGPoint(x: aX, y: 0), animated: false)
                    contentView.bringSubviewToFront(item.element.view)
                }
            } else {
                if item.offset == lastIndex {
                    aX = CGFloat(lastIndex) * aW
                    item.element.view.frame = CGRect(x: aX, y: aY, width: aW, height: aH)
                    contentView.addSubview(item.element.view)
                    contentView.setContentOffset(CGPoint(x: aX, y: 0), animated: false)
                    contentView.bringSubviewToFront(item.element.view)
                }
            }
        }
    }
    /// 初始化子视图
    private func initSubviews() {
        // TODO: 初始化子视图
//        contentView.subviews.forEach { (sub) in
//            sub.removeFromSuperview()
//        }
//        contentView.removeFromSuperview()
        
        addSubview(contentView)
        
        setUpContentView()
    }
    private func setUpContentView() {
        parent?.children.forEach({ (sub) in
            sub.removeFromParent()
        })
        for item in childVces.enumerated() {
            item.element.removeFromParent()
            parent?.addChild(item.element)
        }

        setUpPopGesture()
    }
    private func setUpPopGesture() {
        // 处理返回上级界面手势
        if let navi = parent?.parent as? UINavigationController {
            if navi.viewControllers.count == 1 { return }
            if navi.interactivePopGestureRecognizer != nil {
                contentView.setupScroll { (scrollView, panGesture) -> Bool in
                    let transionX = panGesture?.translation(in: panGesture?.view).x ?? 0.0
                    let offsetX = scrollView?.contentOffset.x ?? 0.0
                    if offsetX == 0 && transionX > 0 {
                        navi.interactivePopGestureRecognizer?.isEnabled = true
                        return false
                    } else {
                        navi.interactivePopGestureRecognizer?.isEnabled = false
                        return true
                    }
                }
            }
        }
    }
    // MARK: - ---> Lazy
    /// 内容区
    private lazy var contentView: ZHScrollView = {
        $0.showsVerticalScrollIndicator = false
        $0.showsHorizontalScrollIndicator = false
        $0.isPagingEnabled = true
        $0.delegate = self
        $0.bounces = style.isContentBounces
        $0.isScrollEnabled = style.isContentScrollEnabled
        return $0
    }(ZHScrollView())
}

/// 重写 gestureRecognizerShouldBegin
/// 处理滑动最左边时,可以使用父类是 NavigationController 的返回手势返回上级页面
class ZHScrollView: UIScrollView {
    typealias ZHScrollViewShouldBeginPanGestureClosure = (ZHScrollView?, UIPanGestureRecognizer?) -> Bool
    private var gestureBeginClosure: ZHScrollViewShouldBeginPanGestureClosure?

    override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        if let gestureBeginClosure = gestureBeginClosure,
           gestureRecognizer == panGestureRecognizer {
            return gestureBeginClosure(self, gestureRecognizer as? UIPanGestureRecognizer)
        } else {
            return super.gestureRecognizerShouldBegin(gestureRecognizer)
        }
    }

    public func setupScroll(_ gestureBeginClosure: @escaping ZHScrollViewShouldBeginPanGestureClosure) {
        self.gestureBeginClosure = gestureBeginClosure
    }
}
extension ZHContentView {
    /// 标题点击事件
    @discardableResult
    public func segmentItemTap(_ index: Int, animated: Bool = true) -> Bool {
        isScroll = false
        let nextIndex = index
        if style.isContentPushAnimaEnabled { // 开启
            if abs(nextIndex - lastIndex) == 1 && animated {
                    isScroll = true
                    contentView.setContentOffset(CGPoint(x: CGFloat(nextIndex) * cWidth, y: 0), animated: isScroll)
            } else {
                if nextIndex != lastIndex {
                    let transition = CATransition()
                    transition.type = .push // 视图转场自带淡入淡出效果
                    transition.subtype = nextIndex > lastIndex ? .fromRight : .fromLeft
                    
                    contentView.layer.add(transition, forKey: nil)
                }
                contentView.setContentOffset(CGPoint(x: CGFloat(index) * cWidth, y: 0), animated: isScroll)
                completedClosure(isScroll, animated: animated)
            }
        } else { // fade 切换
            contentView.layer.add(animTransition(), forKey: nil)
            contentView.setContentOffset(CGPoint(x: CGFloat(index) * cWidth, y: 0), animated: isScroll)
            completedClosure(isScroll, animated: animated)
        }
        return isScroll
    }
    private func completedClosure(_ isScroll: Bool = true, animated: Bool = true) {
        let result = scrollOrTapEnd(scrollView: contentView, isScroll: isScroll)
        if result {
            didScrollViewDidEndScrollingAnimation?(contentView, isScroll, lastIndex, animated)
        }
    }
    // fade 转场切换
    private func animTransition() -> CATransition {
        let transition = CATransition()
        transition.type = .fade
        transition.subtype = .none
        return transition
    }
    // 点击/拖拽结束后
    @discardableResult
    private func scrollOrTapEnd(scrollView: UIScrollView, isScroll: Bool) -> Bool {
        if cWidth == 0 { return false }
        let currentIndex = Int(scrollView.contentOffset.x / cWidth)
        if isScroll { // 控制拖拽 左右边界
            guard currentIndex != lastIndex else { return false }
        }
        
        let lastVc = childVces[lastIndex]
        lastVc.beginAppearanceTransition(false, animated: true)
        lastVc.endAppearanceTransition()
        
        lastIndex = currentIndex
        let currentVc = childVces[currentIndex]
        if currentVc.view.superview == scrollView {
            currentVc.beginAppearanceTransition(true, animated: true)
            currentVc.endAppearanceTransition()
        } else {
            scrollView.layer.add(animTransition(), forKey: nil)
            scrollView.addSubview(currentVc.view)
        }
        // 每次切换都重新布局一次,适配横竖屏切换
        let aX: CGFloat = CGFloat(currentIndex) * cWidth
        let aY: CGFloat = 0
        let aW: CGFloat = cWidth
        let aH: CGFloat = contentView.frame.height
        currentVc.view.frame = CGRect(x: aX, y: aY, width: aW, height: aH)
        // 把当前要展示的放到最顶层来,适配横竖屏切换
        scrollView.bringSubviewToFront(currentVc.view)
        
        return true
    }
}
extension ZHContentView: UIScrollViewDelegate {
    func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        // 处理返回上级界面手势
        if let navi = parent?.parent as? UINavigationController {
            if let popGesture = navi.interactivePopGestureRecognizer {
                popGesture.isEnabled = true
            }
        }
    }
    func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
        // setContentOffset:animated:滑动动画结束时, animated: true 才会调用
        completedClosure()
    }
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        // 拖拽动画结束时
        guard cWidth > 0 else { return }
        scrollViewDidEndScrollingAnimation(scrollView)
    }
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        guard cWidth > 0 else { return }
        guard isScroll else { return }
        let offsetX = scrollView.contentOffset.x
        var direction: ZHScrollDirection
        if offsetX >= beginOffset { // 手指从屏幕右边向左边滑动,内容从左往右滚动
            //print(">>>>")
            direction = .right
        } else {
            //print("<<<<")
            direction = .left
        }
        didScrollViewDidScroll?(scrollView, isScroll, direction)
    }
    func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        isScroll = true
        beginOffset = scrollView.contentOffset.x
        didScrollViewWillBeginDragging?(scrollView)
    }
}
